package com.ruksis.motogeek;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorManager;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;


/**
 * implements incoming sensor data processing in separate thread 
 * @author pzeltins
 *
 */
public class MotoDataProcessor {
	
	private static Queue<SensorEvent> _queue;
	private static Thread _dataProcessor;
	
	private static Messenger _targets[];
	
	/**
	 * 
	 * @param targets that will receive messages with processed data
	 */
	public static void startQueue(Messenger targets[]) {
		
		_targets = targets;
		_queue = new ConcurrentLinkedQueue<SensorEvent>();
		_dataProcessor = new Thread(new Processor());
		_dataProcessor.start();
		
	}
	
	public static void stopQueue() {
		_dataProcessor.interrupt();
	}
	
	public static void push(SensorEvent event) {
		if ( _queue != null ) _queue.add(event);
	}
	
	private static class Processor implements Runnable {

		public void run() {
			
			while ( !Thread.interrupted() ) {
				
				while ( _queue.peek() != null ) {
					processEvent(_queue.poll());
				}
				
			}
			
		}
		
	}
	
	private static float[] _gravity = new float[3];
	private static float[] _geomagnetic = new float[3];

	private static synchronized void processEvent(SensorEvent event) {

		Message _msg = null;
		
		if ( event.sensor.getType() == Sensor.TYPE_ACCELEROMETER ) {
			synchronized (_gravity) {
				System.arraycopy(event.values, 0, _gravity, 0, 3);
			}
		}
		
		if ( event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD ) {
			synchronized (_geomagnetic) {
				System.arraycopy(event.values, 0, _geomagnetic, 0, 3);
			}
		}
		
		if ( event.sensor.getType() == Sensor.TYPE_ACCELEROMETER || event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD ) {

			float[] _rotationMatrix = new float[9];
			float[] _orientation = new float[3];
			
			SensorManager.getRotationMatrix(_rotationMatrix, null, _gravity, _geomagnetic);
			SensorManager.getOrientation(_rotationMatrix, _orientation);
			// need to compute difference between current rot matrix and assumed 0

		} 
		
		if ( event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION ) {
			float gforce = new Float( Math.sqrt( Math.pow(event.values[0],2) + Math.pow(event.values[1],2) + Math.pow(event.values[2],2) ) );
			_msg = MotoMessage.obtainGForceMessage(gforce);
		}
		
		if ( _msg != null ) {
			try {
				for ( Messenger _client : _targets ) {
					_client.send(_msg);
				}
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
		
	}

}
